#include "Plane3D.h"
#include "../../OpenGL.h"
#include "../GameLib.h"
#include "../Logger.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <vector>
#include "Line3D.h" // for testing normal vectors

using std::vector;

Plane3D::Plane3D(){}
Plane3D::Plane3D(Point3D a,Point3D b,Point3D c,Point3D d){
    set(a,b,c,d);
}
Plane3D::~Plane3D(){}
Plane3D& Plane3D::set(Point3D a,Point3D b,Point3D c,Point3D d){
    this->a=a;
    this->b=b;
    this->c=c;
    this->d=d;
    return *this;
}
void Plane3D::drawSolid(){
    glBegin(GL_QUADS);
    a.useAsVertex();
    b.useAsVertex();
    c.useAsVertex();
    d.useAsVertex();
    glEnd();
}
double Plane3D::avg(double in0, double in1, double input){
    //in0 -> 0
    //in1 -> 1
    return (in0*(1.0-input))+(in1*input);
}
void Plane3D::avg(Point3D in0, Point3D in1, double input, Point3D &output){
    output.set(avg(in0.getX(), in1.getX(), input),
               avg(in0.getY(), in1.getY(), input),
               avg(in0.getZ(), in1.getZ(), input));
}
void Plane3D::drawSolid_color(int hexColor){
    float cc[4];
    gameLib.getColorA(cc);
    gameLib.setColor(hexColor);
    drawSolid();
    gameLib.setColorA(cc);
}
void Plane3D::drawTessellated(int tessCountX, int tessCountY){
    Point3D *pts,left,right,aa,bb,cc,dd,u,v;
    Direction3D normal;
    int pos,x,y;
    
    if (tessCountX<0 || tessCountY<0){return;}
    
    pts = new Point3D[(tessCountX+1)*(tessCountY+1)];
    if (!pts)
    {
        errLog.print("Could not malloc. [Plane3D::drawTessellated(int,int)]");
        assert(!"Could not malloc. [Plane3D::drawTessellated(int,int)]");
    }
    pos = 0;
    
    for (y=0;y<=tessCountY;y++)
    {
        avg(a,d,y/(float)tessCountY,left);
        avg(b,c,y/(float)tessCountY,right);
        for (x=0;x<=tessCountX;x++)
        {
            avg(left,right,x/(float)tessCountX,pts[pos]);
            pos++;
        }
    }
    //mainLog.print("The surface normals are:");
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
    glBegin(GL_QUADS);
    for (y=0;y<tessCountY;y++)
    {
        for (x=0;x<tessCountX;x++)
        {
            aa=pts[x  +( y   *(tessCountX+1))];
            bb=pts[x+1+( y   *(tessCountX+1))];
            cc=pts[x+1+((y+1)*(tessCountX+1))];
            dd=pts[x  +((y+1)*(tessCountX+1))];

            gameLib.calculateNormalTriangle(cc,bb,aa,normal);
            gameLib.setNormal(normal);
            aa.useAsVertex();
            bb.useAsVertex();
            cc.useAsVertex();
            dd.useAsVertex();
            /*u=aa+=bb+=cc+=dd;
            u.set(u.getX()/4, u.getY()/4, u.getZ()/4);
            v=u;
            v.move(normal, 5.0);
            glEnd();
            Line3D().set(u,v).draw_widthColor(2.0, C_GREEN);
            glBegin(GL_QUADS);*/
        }
    }
    glEnd();
    
    //mainLog.print("End surface normals.");
    
    delete []pts;
}
void Plane3D::drawTessellatedWireframe(int tessCountX, int tessCountY){
    Point3D alpha,bravo;
    int x,y;
    
    if (tessCountX<0 || tessCountY<0){return;}
    
    //pts = new Point3D[(tessCountX+1)*(tessCountY+1)];
    //if (!pts){errLog.print("Could not malloc. [Plane3D::drawTessellatedWireframe(int,int)]");return;}
    
    glBegin(GL_LINES);
    for (y=0;y<=tessCountY;y++)
    {
        avg(a,d,y/(float)tessCountY,alpha);
        avg(b,c,y/(float)tessCountY,bravo);
		alpha.useAsVertex();
		bravo.useAsVertex();
    }
	for (x=0;x<=tessCountX;x++)
	{
		avg(a, b, x/(float)tessCountX, alpha);
		avg(d, c, x/(float)tessCountX, bravo);
		alpha.useAsVertex();
		bravo.useAsVertex();
	}
    glEnd();
}
void Plane3D::drawPerim(){
    glBegin(GL_LINES);
    a.useAsVertex();
    b.useAsVertex();
    b.useAsVertex();
    c.useAsVertex();
    c.useAsVertex();
    d.useAsVertex();
    d.useAsVertex();
    a.useAsVertex();
    glEnd();
}
void Plane3D::drawPerim_color(int hexColor){
    float cc[4];
    gameLib.getColorA(cc);
    gameLib.setColor(hexColor);
    drawPerim();
    gameLib.setColorA(cc);
}